package thread;
/**
 * 线程并发安全问题
 * 同步块:
 *  synchronized(同步监视器对象){
 *      需要多个线程同时执行的代码代码
 *  }
 */
public class SyncDemo1 {
    public static void main(String[] args) {
        /*
        Shop shop = new Shop();
        Thread t1 = new Thread("王克晶"){
            public void run(){
                shop.buy();
            }
        };
        Thread t2 = new Thread("范传奇"){
            public void run(){
                shop.buy();
            }
        };
        Thread t1 = new Thread(shop::buy);
        Thread t2 = new Thread(shop::buy);
        t1.start();
        t2.start();
         */

        Shop shop1 = new Shop();
        Shop shop2 = new Shop();
        /*
        Thread t1 = new Thread("王克晶"){
            public void run(){
                shop1.buy();
            }
        };
        Thread t2 = new Thread("范传奇"){
            public void run(){
                shop2.buy();
            }
        };
         */
        Thread t1 = new Thread(shop1::buy);
        Thread t2 = new Thread(shop2::buy);
        t1.start();
        t2.start();
    }
}

class Shop{
    //public synchronized void buy(){ //在方法上同步监视(加锁)，范围比较大，同步监视对象只能是this
    public void buy(){
        try {
            Thread t = Thread.currentThread();
            System.out.println(t.getName()+": 正在挑衣服");
            Thread.sleep(3000);
            /*
             同步监视块，缩小了监视范围
             同步监视对象通常使用:临界资源
             临界资源:抢谁谁就是临界资源，说白了，抢谁就锁谁
             */
            //synchronized(new Object()) { //永远不能用实例化的对象作为同步监视器对象，一定无效
            //synchronized(123){ //同步监视器对象一定是引用类型
            //synchronized("abc"){ //虽然可以锁上，但abc并不是合适的锁对象
            synchronized(this) { //this为锁对象，锁的当前shop对象。只要是同一个对象，就一定会被锁住
                System.out.println(t.getName() + ": 正在试衣服");
                Thread.sleep(3000);
            }
            System.out.println(t.getName()+": 结账离开");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}














